﻿using Aop.Api.Util;
using DTcms.Common;
using MintCyclingService.UserAccount;
using MintCyclingService.UserRecharge;
using MintCyclingService.Utils;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Text;
using Utility.Common;
using Utility.LogHelper;

namespace MintCyclingWebApi
{
    public partial class notify_url : System.Web.UI.Page
    {
        //获取配置文件中的值
        private static string AppID = System.Web.Configuration.WebConfigurationManager.AppSettings["AppID"];                      //APPID
        private static string App_private_Key = System.Web.Configuration.WebConfigurationManager.AppSettings["App_private_Key"];         //私钥
        private static string Alipay_public_Key = System.Web.Configuration.WebConfigurationManager.AppSettings["Alipay_public_Key"];     //公钥
        private static string Charset = System.Web.Configuration.WebConfigurationManager.AppSettings["Charset"];             //编码方式
        private static string SellerID = System.Web.Configuration.WebConfigurationManager.AppSettings["SellerID"];           //收款支付宝用户ID
        private static string notifUrl = System.Web.Configuration.WebConfigurationManager.AppSettings["notify_url"];         //获取服务器异步通知页面路径

 
        //支付宝通知验证路径
        private string Https_veryfy_url = "https://mapi.alipay.com/gateway.do?service=notify_verify&";

        //接口实例化
        private IUserAccountService _UserAccountService = new UserAccountService();
        private IUserRechargeRecordService _UserRechargeService = new UserRechargeRecordService();

        protected void Page_Load(object sender, EventArgs e)
        {
            //获取所有异步通知参数
            IDictionary<string, string> dic = GetRequestPost();
            //FileLog.Log("参数个数" + dic.Count, "AsyncAlipay");
            if (dic.Count > 0)  //判断是否有带返回参数
            {
                #region 验证签名和验证是否是支付宝发来的通知
         
                try
                {
                    //验证签名调用
                    bool CheckFlag = AlipaySignature.RSACheckV1(dic, Alipay_public_Key, Charset, "RSA2", false);
                    //是否是支付宝发来的通知
                    bool verifyResult = Verify(dic, DTRequest.GetString("notify_id"), DTRequest.GetString("sign"));

                    //日志-测试用
                    //FileLog.Log("flag:"+flag+"verifyResult:" + verifyResult, "AsyncAlipay");

                    #region 处理订单的业务逻辑

                    //验签通过并且同时验证是否是支付宝发来的通知同时成立--验证签名及notify_id合法性校验都是true的判断逻辑里
                    if (CheckFlag && verifyResult)
                    {
                        string trade_no = DTRequest.GetString("trade_no");                       //支付宝交易号
                        string out_trade_no = DTRequest.GetString("out_trade_no").ToUpper();     //获取订单号
                        string total_amount = DTRequest.GetString("total_amount");             //获取总金额
                        string trade_status = DTRequest.GetString("trade_status");            //交易状态
                        string sellerID = DTRequest.GetString("seller_id");                   //卖家支付宝用户号
                        string app_id = DTRequest.GetString("app_id");
                        DateTime gmt_payment = DateTime.Parse(DTRequest.GetString("gmt_payment"));
                        string sign = DTRequest.GetString("Sign");
                        string sign_type = DTRequest.GetString("Sign_type");

                        //日志
                        LogHelper.Info("平台订单号：" + out_trade_no + ",交易状态" + trade_status+"，时间："+DateTime.Now);

                        int tradeStatus = GetTradeStatus(trade_status); //交易状态
                        //交易完成和支付完成时
                        if (trade_status == "TRADE_FINISHED" || trade_status == "TRADE_SUCCESS")
                        {
                            //公共校验----校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方
                            if (SellerID != sellerID)
                            {
                                System.Web.HttpContext.Current.Response.Write("failure");
                                return;
                            }

                            if (AppID != app_id)
                            {
                                System.Web.HttpContext.Current.Response.Write("failure");
                                return;
                            }

                            //用户充值押金或者退押金----------修改账户余额订单状态信息公用实体Model
                            UserReDepositUpdate_PM model = new UserReDepositUpdate_PM();
                            model.Status = tradeStatus; //修改状态
                            model.out_trade_no = out_trade_no;
                            model.gmt_payment = gmt_payment;
                            model.trade_no = trade_no;
                            model.sign = sign;
                            model.sign_type = sign_type;
                            model.total_amount = decimal.Parse(total_amount);

                            var result = new ResultModel();

                            //处理订单的业务逻辑
                            if (out_trade_no.StartsWith("YE")) //余额充值
                            {
                                #region 处理余额相关业务逻辑

                                #region 校验通知数据的正确性

                                result = _UserRechargeService.GetUserRechargeRecordByout_trade_no(out_trade_no, total_amount);
                                if (!result.IsSuccess)
                                {
                                    System.Web.HttpContext.Current.Response.Write("failure");
                                    return;
                                }
                                else if (result.IsSuccess && result.MsgCode == "1")
                                {
                                    System.Web.HttpContext.Current.Response.Write("success");
                                    return;
                                }else
                                {
                                    bool flag = _UserRechargeService.UserRechargeOrAccountInfo(model);
                                    if (!flag)
                                    {
                                        //日志
                                        LogHelper.Info("提交账户余额数据失败，平台订单号：" + out_trade_no + ",时间：" + DateTime.Now + ",充值状态：" + tradeStatus);
                                        System.Web.HttpContext.Current.Response.Write("failure");
                                        return;
                                    }
                                    //发送短信消息通知用户
                                    Guid userGuid = new Guid();
                                    string T = "余额";

                                    string remark = "【薄荷单车】您账户" + DateTime.Now.Month + "月" + DateTime.Now.Day + "日" + "收到余额充值\"" + model.total_amount + "\"元,请及时查看。";
                                    bool flg = _UserAccountService.UsersSendSMS(userGuid, out_trade_no, T, remark);
                                }
                                #endregion 校验通知数据的正确性

                                #endregion 处理余额相关业务逻辑
                            }
                            else //充值押金
                            {
                                #region 处理押金相关业务逻辑

                                #region 校验通知数据的正确性
                                result = _UserAccountService.GetUserDepositByout_trade_no(out_trade_no, total_amount);
                                if (!result.IsSuccess)
                                {
                                    System.Web.HttpContext.Current.Response.Write("failure");
                                    return;
                                }
                                else if (result.IsSuccess && result.MsgCode == "1")
                                {
                                    System.Web.HttpContext.Current.Response.Write("success");
                                    return;
                                }
                                else
                                {
                                    //FileLog.Log("测试model"+ model, "AsyncAlipay");
                                    bool flag = _UserAccountService.UserReOrUpdateDeposit(model);
                                    //FileLog.Log("1111：" + out_trade_no + ",修改押金的flg：" + flag, "111111");
                                    if (!flag)
                                    {
                                        //日志
                                        LogHelper.Info("提交充值押金数据失败，平台订单号：" + out_trade_no + ",时间：" + DateTime.Now + ",充值状态：" + tradeStatus);
                                        System.Web.HttpContext.Current.Response.Write("failure");
                                        return;
                                    }
                                    //发送短信消息通知用户
                                    Guid userGuid = new Guid();
                                    string T = "押金";

                                    string remark = "【薄荷单车】您账户" + DateTime.Now.Month + "月" + DateTime.Now.Day + "日" + "收到押金充值\"" + model.total_amount + "\"元,请及时查看。";
                                    bool flg = _UserAccountService.UsersSendSMS(userGuid, out_trade_no,T, remark);
                                    LogHelper.Info("提交充值押金数据成功：" + out_trade_no + ",交易状态" + trade_status);
                                }

                                #endregion 校验通知数据的正确性

                                #endregion 处理押金相关业务逻辑
                            }
                        }
                        else if (trade_status == "TRADE_CLOSED") //交易关闭
                        {
                            //日志
                            LogHelper.Info("平台订单号：" + out_trade_no + "，支付宝交易订单号：" + trade_no + ",时间：" + DateTime.Now + "交易状态:" + trade_status);
                            System.Web.HttpContext.Current.Response.Write("failure");
                            return;
                        }
                        else //充值失败
                        {
                            //日志
                            LogHelper.Info("验证签名和验证是否是支付宝发来的通知，充值失败，平台订单号：" + out_trade_no + ",充值时间：" + DateTime.Now + ",验证签名状态为:" + CheckFlag + "是否是支付宝发来的通知状态为：" + verifyResult);
                            System.Web.HttpContext.Current.Response.Write("failure");
                            return;
                        }
                        //日志
                        // FileLog.Log("验证签名和验证是否是支付宝发来的通知，充值成功,充值时间：" + DateTime.Now + ",支付宝交易号为:" + trade_no + "获取订单号：" + out_trade_no + "获取总金额：" + total_amount + "交易状态：" + trade_status, typeName);
                        System.Web.HttpContext.Current.Response.Write("success");  //充值成功
                        return;
                    }
                    else //支付宝验签失败，请检查对应的接口调用
                    {
                        System.Web.HttpContext.Current.Response.Write("failure");
                        return;
                    }

                    #endregion 处理订单的业务逻辑
                }
                catch (Exception ex)
                {
                    //日志
                    LogHelper.Error("验证签名出现异常，异步通知参数个数为:" + dic.Count + ex);
                    System.Web.HttpContext.Current.Response.Write("failure");
                    return;
                }

                #endregion 验证签名和验证是否是支付宝发来的通知
            }
            else
            {
                //日志
                LogHelper.Info("返回异步通知参数错误，日期：" + DateTime.Now + ",异步通知参数个数为:" + dic.Count);
                System.Web.HttpContext.Current.Response.Write("failure");
                return;
            }
        }


        #region  支付宝API
        /// <summary>
        ///  验证消息是否是支付宝发出的合法消息
        /// </summary>
        /// <param name="inputPara">通知返回参数数组</param>
        /// <param name="notify_id">通知验证ID</param>
        /// <param name="sign">支付宝生成的签名结果</param>
        /// <returns>验证结果</returns>
        public bool Verify(IDictionary<string, string> inputPara, string notify_id, string sign)
        {
            ////获取返回回来的待签名数组签名后结果
            //string mysign = GetResponseMysign(inputPara);
            //获取是否是支付宝服务器发来的请求的验证结果
            string responseTxt = "true";
            if (notify_id != "") { responseTxt = GetResponseTxt(notify_id); }

            //写日志记录（若要调试，请取消下面两行注释）
            //string sWord = "responseTxt=" + responseTxt + "\n sign=" + sign + "&mysign=" + mysign + "\n 返回回来的参数：" + GetPreSignStr(inputPara) + "\n ";
            //Core.LogResult(sWord);

            //验证
            //responsetTxt的结果不是true，与服务器设置问题、合作身份者ID、notify_id一分钟失效有关
            //mysign与sign不等，与安全校验码、请求时的参数格式（如：带自定义参数等）、编码格式有关
            if (responseTxt == "true")//验证成功
            {
                return true;
            }
            else//验证失败
            {
                return false;
            }
        }

        /// <summary>
        /// 获取是否是支付宝服务器发来的请求的验证结果
        /// </summary>
        /// <param name="notify_id">通知验证ID</param>
        /// <returns>验证结果</returns>
        private string GetResponseTxt(string notify_id)
        {
            string veryfy_url = Https_veryfy_url + "partner=" + SellerID + "&notify_id=" + notify_id;

            //获取远程服务器ATN结果，验证是否是支付宝服务器发来的请求
            string responseTxt = Get_Http(veryfy_url, 120000);  //2分钟120秒

            return responseTxt;
        }

        /// <summary>
        /// 获取远程服务器ATN结果
        /// </summary>
        /// <param name="strUrl">指定URL路径地址</param>
        /// <param name="timeout">超时时间设置</param>
        /// <returns>服务器ATN结果</returns>
        private string Get_Http(string strUrl, int timeout)
        {
            string strResult;
            try
            {
                HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(strUrl);
                myReq.Timeout = timeout;
                HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse();
                Stream myStream = HttpWResp.GetResponseStream();
                StreamReader sr = new StreamReader(myStream, Encoding.Default);
                StringBuilder strBuilder = new StringBuilder();
                while (-1 != sr.Peek())
                {
                    strBuilder.Append(sr.ReadLine());
                }
                strResult = strBuilder.ToString();
            }
            catch (Exception exp)
            {
                strResult = "错误：" + exp.Message;
                LogHelper.Error("获取远程服务器ATN结果异常，" + strResult);
            }
            return strResult;
        }

        /// 获取支付宝主动发送POST过来通知消息，并以“参数名=参数值”的形式组成数组
        /// request回来的信息组成的数组
        public static IDictionary<string, string> GetRequestPost()
        {
            int i = 0;
            //创建泛型哈希表，然后加入元素
            IDictionary<string, string> sArray = new Dictionary<string, string>(); //将异步通知中收到的待验证所有参数都存放到IDictionary中
            NameValueCollection coll;
            try
            {
                //表单变量加载到NameValueCollection变量
                coll = System.Web.HttpContext.Current.Request.Form;

                //得到所有形式的名字添加到一个字符串数组
                String[] requestItem = coll.AllKeys;

                for (i = 0; i < requestItem.Length; i++)
                {
                    sArray.Add(requestItem[i], System.Web.HttpContext.Current.Request.Form[requestItem[i]]);
                }
            }
            catch (Exception ex)
            {
                //日志
                LogHelper.Info("获取支付宝主动发送POST过来通知消息组成的数组" + sArray);
            }

            return sArray;
        }

        /// <summary>
        /// 交易状态说明
        /// </summary>
        /// <param name="T"></param>
        /// <returns></returns>
        public static int GetTradeStatus(string T)
        {
            //充值的状态：0充值失败()；1充值成功--TRADE_SUCCESS；2交易创建，等待买家付款--WAIT_BUYER_PAY；3.未付款交易超时关闭，或支付完成后全额退款--TRADE_CLOSED；4.交易结束，不可退款--TRADE_FINISHED
            int str = 0;
            switch (T)
            {
                case "TRADE_SUCCESS":
                    str = 1;
                    break;

                case "WAIT_BUYER_PAY":
                    str = 2;
                    break;

                case "TRADE_CLOSED":
                    str = 3;
                    break;

                case "TRADE_FINISHED":
                    str = 4;
                    break;

                default:
                    str = 0;
                    break;
            }
            return str;
        }

        #endregion


    }
}